主成分分析(Principle Component Analysis, PCA)
Overview
主成分分析は、データセットの特徴量を相互に統計的に関連しないように回転する手法です。データの可視化や圧縮などの目的によく用いられます。
Theory
主成分分析は、まず最も分散が大きい方向を見つけ、それに「第1成分」というラベルを付けます。データはこの方向に対して最も情報を持ちます。つまりこの方向は、特徴量が最も相互に関係する方向です。次に第1成分と直行する方向の中から、最も情報を持っている方向を探します。ここで、2つの成分は傾きと大きさだけが重要で、矢がどちらを向いているかは関係ありません。
このようにして見つけていく「方向」を、主成分と呼びます。この方向がデータの分散が存在する主要な方向だからです。一般には、もとの特徴量と同じ数だけ主成分が存在します。
主成分分析を用いたデータ変換
https://gyazo.com/e7eff875052b3bcacddc6d4d56ab3ecb
左上のプロット:もとのデータを示しています。データの分散が存在する主要な方向(主成分)に矢印が向いています。
右上のプロット:Component1がx軸、Component2がy軸に沿うように回転させたものです。原点の周辺にデータが来るように平均を引いて調整しています。
左下のプロット:Component1だけを取り出し、1次元のデータセットにしています。
右下のプロット:Component1をもとの方向に回転し、平均を足して、データをもとに戻しています。
こうすることで、データポイントはもとの特徴量空間にありますが、Component1に含まれている情報しか維持されていません。このような変換は、データからノイズを取り除いたり、情報を可視化されるために用いられます。(次元削減)
Coding
cancerデータセットをPCAを用いて可視化する
PCAの最も一般的な用途は、高次元なデータセットの可視化です。cancerデータセットには30もの特徴量があるので理解するのが難しいです。そこでPCAを用います。
code: Python
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
cancer = load_breast_cancer()
# スケール変換
scaler = StandardScaler()
scaler.fit(cancer.data)
X_scaled = scaler.transform(cancer.data)
# データの最初の2つの主成分だけ維持する
pca = PCA(n_components=2)
pca.fit(X_scaled)
X_pca = pca.transform(X_scaled)
print('Original shape: {}'.format(str(X_scaled.shape)))
print('Reduced shape: {}'.format(str(X_pca.shape)))
# 第1主成分と第2主成分によるプロット
plt.figure(figsize=(8, 8))
mglearn.discrete_scatter(X_pca:, 0, X_pca:, 1, cancer.target) plt.legend(cancer.target_names, loc="best")
plt.gca().set_aspect("equal")
plt.xlabel("First principal component")
plt.ylabel("Second principal component")
--------------------------------------------------------------------------
Original shape: (569, 30)
Reduced shape: (569, 2)
--------------------------------------------------------------------------
https://gyazo.com/ea43cbebc311e398bd532a63649fc6e7
これを見ると、線形クラス分類器でもそれなりに分類できそうなことがわかります。また、悪性のデータポイントは、良性のデータポイントよりも広がっていることがわかります。
Advanced
PCAの欠点は、プロットした2つの軸の解釈が容易ではないことです。主成分は、PCAの適合を行う過程で、components_属性に格納されています。components_のそれぞれの行が1つの主成分に対応します。行は重要度によってソートされています(第1主成分が最初に来ます)。列は、PCA変換する前のもとの特徴量に対応します。
code: Python
print('PCA components:\n{}'.format(pca.components_))
# ヒートマップで可視化する
plt.matshow(pca.components_, cmap='viridis')
plt.colorbar()
plt.xticks(range(len(cancer.feature_names)),
cancer.feature_names, rotation=60, ha='left')
plt.xlabel("Feature")
plt.ylabel("Principal components")
--------------------------------------------------------------------------
PCA components:
[[ 0.21890244 0.10372458 0.22753729 0.22099499 0.14258969 0.23928535
0.25840048 0.26085376 0.13816696 0.06436335 0.20597878 0.01742803
0.21132592 0.20286964 0.01453145 0.17039345 0.15358979 0.1834174
0.04249842 0.10256832 0.22799663 0.10446933 0.23663968 0.22487053
0.12795256 0.21009588 0.22876753 0.25088597 0.12290456 0.13178394]
[-0.23385713 -0.05970609 -0.21518136 -0.23107671 0.18611302 0.15189161
0.06016536 -0.0347675 0.19034877 0.36657547 -0.10555215 0.08997968
-0.08945723 -0.15229263 0.20443045 0.2327159 0.19720728 0.13032156
0.183848 0.28009203 -0.21986638 -0.0454673 -0.19987843 -0.21935186
0.17230435 0.14359317 0.09796411 -0.00825724 0.14188335 0.27533947]]
--------------------------------------------------------------------------
https://gyazo.com/5b33446b267ff53b8ba896b1af3eb8d1
第1主成分を見ると、すべての特徴量が同じ符号になっていることがわかります。これは、すべての特徴量に一般的な相関があり、ある特徴量が大きければ、ほかの特徴量も大きくなる傾向にあります。
// TODO P144をまとめる